#ifndef _conditions__hpp_lkjjwfejiojoiwef93323290i98u9hy7yf43jifejji2efjnvnjv__
#define _conditions__hpp_lkjjwfejiojoiwef93323290i98u9hy7yf43jifejji2efjnvnjv__

#include <functional>

#include "../base/base_type.hpp"

namespace hude
{
	namespace utils
	{
		namespace _temp_n
		{
			/**********************************************************************************************
			* @brief _conds_int_test_t
			*/
			template< int _size > struct _conds_int_test_t;

			template<> struct _conds_int_test_t< 1 > { typedef uint8_t  type_t; };
			template<> struct _conds_int_test_t< 2 > { typedef uint16_t type_t; };
			template<> struct _conds_int_test_t< 3 > { typedef uint32_t type_t; };
			template<> struct _conds_int_test_t< 4 > { typedef uint32_t type_t; };
			template<> struct _conds_int_test_t< 5 > { typedef uint64_t type_t; };
			template<> struct _conds_int_test_t< 6 > { typedef uint64_t type_t; };
			template<> struct _conds_int_test_t< 7 > { typedef uint64_t type_t; };
			template<> struct _conds_int_test_t< 8 > { typedef uint64_t type_t; };

			/**********************************************************************************************
			* @brief _power_t
			*/
			template< int _base, int _power > struct _power_t { enum { emVALUE = _base * _power_t< _base, _power - 1 >::emVALUE }; };
			template< int _base > struct _power_t< _base, 1 > { enum { emVALUE = _base }; };

		} //namespace _temp_n

		/**********************************************************************************************
		* @brief conds_args_t
		*/
		template< int _count > struct conds_args_t
		{
			typedef typename _temp_n::_conds_int_test_t< _count / 8 + ( ( _count % 8 ) ? 1 : 0 ) >::type_t type_t;

			enum { emCOUNT = _count, emFULL = _temp_n::_power_t< 2, _count >::emVALUE - 1 };
		};

		/**********************************************************************************************
		* @brief condsitions_t
		*/
		template< int _count >
		class condsitions_t
		{
		public:
			typedef conds_args_t< _count > args_t;

			enum { emCount = _count, emFULL = args_t::emFULL };

			typedef typename args_t::type_t type_t;

			typedef std::function< void( condsitions_t& ) > cb_t;

		private:
			cb_t cb_;
			type_t bits_, trigger_;
			bool state_;

		public:
			condsitions_t( cb_t cb, type_t init = type_t(), type_t trigger = emFULL, bool first = true ) :
				cb_( cb ), bits_( init ), trigger_( trigger ), state_( this->trigger( init ) )
			{
				if ( first && cb_ ) cb_( *this );
			}

			bool trigger( type_t v ) const { return v == static_cast< type_t >( trigger_ ); }

			void set( int n, bool b )
			{
				if ( n < emCount )
				{
					if ( b ) {
						bits_ |= type_t( 1 << n );
					} else {
						bits_ &= ~ type_t( 1 << n );
					}

					bool tmp = trigger( bits_ );

					if ( tmp != state_ )
					{
						state_ = tmp;

						if ( cb_ ) cb_( *this );
					}
				}
			}

			bool get() const { return state_; }

			operator bool() const { return get(); }
		};

	} //namespace utils
} //namespace hude

#endif //_conditions__hpp_lkjjwfejiojoiwef93323290i98u9hy7yf43jifejji2efjnvnjv__

